from rest_framework import serializers
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from .models import User
from django.core.validators import RegexValidator
from django.utils import timezone
import re


class VerificationCodeSerializer(serializers.Serializer):
    """验证码序列化器"""
    phone = serializers.CharField(
        max_length=11,
        min_length=11,
        required=True,
        error_messages={
            'required': '请输入手机号',
            'max_length': '手机号长度必须为11位',
            'min_length': '手机号长度必须为11位'
        }
    )
    verification_code = serializers.CharField(
        max_length=6,
        min_length=6,
        required=False,  # 发送验证码时不需要此字段
        error_messages={
            'max_length': '验证码长度必须为6位',
            'min_length': '验证码长度必须为6位'
        }
    )

    def validate_phone(self, value):
        """验证手机号格式"""
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确')
        return value


class UserRegistrationSerializer(serializers.ModelSerializer):
    """用户注册序列化器"""
    password = serializers.CharField(
        write_only=True,
        required=True,
        allow_blank=False,
        error_messages={
            'blank': '密码不能为空',
            'required': '密码不能为空'
        },
        help_text='密码'
    )
    password_confirm = serializers.CharField(
        write_only=True,
        required=True,
        allow_blank=False,
        error_messages={
            'blank': '确认密码不能为空',
            'required': '确认密码不能为空'
        },
        help_text='确认密码'
    )
    phone = serializers.CharField(
        max_length=11,
        validators=[
            RegexValidator(
                regex=r'^1[3-9]\d{9}$',
                message='手机号格式不正确'
            )
        ]
    )

    class Meta:
        model = User
        fields = ['phone', 'password', 'password_confirm']
        extra_kwargs = {
            'password': {'write_only': True},
            'password_confirm': {'write_only': True},
        }

    def validate(self, attrs):
        """验证密码和验证码"""
        print("Received attrs:", attrs)  # Debug logging

        # 验证密码是否为空
        if not attrs.get('password') or not attrs.get('password_confirm'):
            raise serializers.ValidationError({"password": "密码不能为空"})

        # 验证密码是否匹配
        if attrs['password'] != attrs['password_confirm']:
            raise serializers.ValidationError({"password": "两次输入的密码不一致"})

        # 从缓存获取验证码
        from django.core.cache import cache
        cache_key = f"verification_code_{attrs['phone']}"
        cached_code = cache.get(cache_key)

        if not cached_code:
            raise serializers.ValidationError({"verification_code": "请先获取验证码"})

        if cached_code != attrs.get('verification_code'):
            raise serializers.ValidationError({"verification_code": "验证码错误"})

        # 验证验证码是否过期（5分钟有效期）
        cache_timeout = cache.ttl(cache_key)
        if cache_timeout is None or cache_timeout <= 0:
            raise serializers.ValidationError({"verification_code": "验证码已过期"})

        return attrs

    def create(self, validated_data):
        """创建用户"""
        from django.db import transaction, IntegrityError
        import time
        from django.core.exceptions import ObjectDoesNotExist

        print("Validated data:", validated_data)  # Debug

        max_retries = 3
        retry_delay = 0.1  # 初始模拟延迟

        for attempt in range(max_retries):
            try:
                with transaction.atomic():
                    # 使用select_for_update锁定用户记录
                    user = User.objects.select_for_update().filter(
                        phone=validated_data['phone']
                    ).first()

                    if user:
                        # 如果用户已存在，更新密码
                        user.set_password(validated_data['password'])
                        user.verification_code = None
                        user.code_sent_at = None
                        user.save()
                    else:
                        # 创建新用户
                        user = User.objects.create(
                            phone=validated_data['phone'],
                            verification_code=None,
                            code_sent_at=None
                        )
                        user.set_password(validated_data['password'])
                        user.save()

                    return user

            except IntegrityError as e:
                if attempt == max_retries - 1:
                    raise serializers.ValidationError({
                        'phone': '注册失败，请稍后重试'
                    })
                # 指数退避重试
                time.sleep(retry_delay * (2 ** attempt))
                continue

            except ObjectDoesNotExist:
                if attempt == max_retries - 1:
                    raise serializers.ValidationError({
                        'phone': '注册失败，请稍后重试'
                    })
                time.sleep(retry_delay * (2 ** attempt))
                continue

    def validate_password(self, value):
        """
        密码验证增强
        """
        if len(value) < 8:
            raise serializers.ValidationError("密码长度至少为8个字符")
        if not any(char.isdigit() for char in value):
            raise serializers.ValidationError("密码必须包含至少一个数字")
        if not any(char.isalpha() for char in value):
            raise serializers.ValidationError("密码必须包含至少一个字母")
        return value


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    """自定义JWT Token获取序列化器"""
    username_field = 'phone'

    @classmethod
    def get_token(cls, user):
        """生成包含额外信息的Token"""
        token = super().get_token(user)
        # 添加自定义声明
        token['username'] = user.username
        token['phone'] = user.phone
        return token

    def validate(self, attrs):
        data = super().validate(attrs)
        # 更新最后登录时间
        self.user.last_login = timezone.now()
        self.user.save(update_fields=['last_login'])
        return data


class UserSerializer(serializers.ModelSerializer):
    """用户信息序列化器"""
    masked_phone = serializers.SerializerMethodField()
    avatar_url = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id', 'phone', 'masked_phone', 'username', 'email',
                  'created_at', 'updated_at', 'last_login', 'avatar', 'avatar_url')
        read_only_fields = ('phone', 'created_at', 'updated_at',
                            'last_login', 'masked_phone')

    def get_masked_phone(self, obj):
        """返回加密的手机号"""
        return obj.phone[:3] + '****' + obj.phone[-4:]

    def get_avatar_url(self, obj):
        """返回完整的头像URL"""
        if obj.avatar:
            request = self.context.get('request')
            if request:
                return request.build_absolute_uri(obj.avatar.url)
        return None

    def validate_username(self, value):
        if len(value) < 3 or len(value) > 20:
            raise serializers.ValidationError("用户名长度应在3到20个字符之间")

        # 检查用户名是否已存在
        if self.instance and self.instance.username == value:
            return value

        if User.objects.filter(username=value).exists():
            raise serializers.ValidationError("用户名已存在")

        # 检查用户名格式（只允许字母、数字和下划线）
        if not value.isalnum() and '_' not in value:
            raise serializers.ValidationError("用户名只能包含字母、数字和下划线")

        return value

    def validate_email(self, value):
        if not value:
            return value

        # 验证邮箱格式
        if '@' not in value or '.' not in value.split('@')[1]:
            raise serializers.ValidationError("邮箱格式不正确")

        # 检查邮箱是否已存在
        if self.instance and self.instance.email == value:
            return value

        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError("邮箱已被使用")

        return value


class PasswordChangeSerializer(serializers.Serializer):
    old_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True)
    new_password_confirm = serializers.CharField(required=True)


class UserLoginSerializer(serializers.Serializer):
    """用户登录序列化器"""
    phone = serializers.CharField(
        required=True,
        error_messages={
            'required': '手机号不能为空',
            'blank': '手机号不能为空'
        }
    )
    password = serializers.CharField(
        required=True,
        write_only=True,
        error_messages={
            'required': '密码不能为空',
            'blank': '密码不能为空'
        }
    )

    def validate_phone(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确')
        return value
